{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Deep_Q_Learning_Cart_Pole_balancing.ipynb",
      "provenance": [],
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/PacktPublishing/Modern-Computer-Vision-with-PyTorch/blob/master/Chapter16/Deep_Q_Learning_Cart_Pole_balancing.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "EAsxgBMbnOlT"
      },
      "source": [
        "import gym\n",
        "import numpy as np\n",
        "import cv2\n",
        "from collections import deque\n",
        "import torch\n",
        "import torch.nn as nn\n",
        "import torch.nn.functional as F\n",
        "import numpy as np\n",
        "import random\n",
        "from collections import namedtuple, deque\n",
        "import torch\n",
        "import torch.nn.functional as F\n",
        "import torch.optim as optim\n",
        "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3ANvz1Z_nWDz"
      },
      "source": [
        "env = gym.make('CartPole-v1')"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "NXyrPGJSnXpp"
      },
      "source": [
        "class DQNetwork(nn.Module):\n",
        "    def __init__(self, state_size, action_size):\n",
        "        super(DQNetwork, self).__init__()\n",
        "        \n",
        "        self.fc1 = nn.Linear(state_size, 24)\n",
        "        self.fc2 = nn.Linear(24, 24)\n",
        "        self.fc3 = nn.Linear(24, action_size)\n",
        "        \n",
        "    def forward(self, state):       \n",
        "        x = F.relu(self.fc1(state))\n",
        "        x = F.relu(self.fc2(x))\n",
        "        x = self.fc3(x)\n",
        "        return x\n"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Fxxt2zRGnczv"
      },
      "source": [
        "class Agent():\n",
        "    def __init__(self, state_size, action_size):\n",
        "        \n",
        "        self.state_size = state_size\n",
        "        self.action_size = action_size\n",
        "        self.seed = random.seed(0)\n",
        "\n",
        "        ## hyperparameters\n",
        "        self.buffer_size = 2000\n",
        "        self.batch_size = 64\n",
        "        self.gamma = 0.99\n",
        "        self.lr = 0.0025\n",
        "        self.update_every = 4 \n",
        "\n",
        "        # Q-Network\n",
        "        self.local = DQNetwork(state_size, action_size).to(device)\n",
        "        self.optimizer = optim.Adam(self.local.parameters(), lr=self.lr)\n",
        "\n",
        "        # Replay memory\n",
        "        self.memory = deque(maxlen=self.buffer_size) \n",
        "        self.experience = namedtuple(\"Experience\", field_names=[\"state\", \"action\", \"reward\", \"next_state\", \"done\"])\n",
        "        self.t_step = 0\n",
        "    def step(self, state, action, reward, next_state, done):\n",
        "        # Save experience in replay memory\n",
        "        self.memory.append(self.experience(state, action, reward, next_state, done)) \n",
        "        # Learn every update_every time steps.\n",
        "        self.t_step = (self.t_step + 1) % self.update_every\n",
        "        if self.t_step == 0:\n",
        "            # If enough samples are available in memory, get random subset and learn\n",
        "            if len(self.memory) > self.batch_size:\n",
        "                experiences = self.sample_experiences()\n",
        "                self.learn(experiences, self.gamma)\n",
        "    def act(self, state, eps=0.):\n",
        "        # Epsilon-greedy action selection\n",
        "        if random.random() > eps:\n",
        "            state = torch.from_numpy(state).float().unsqueeze(0).to(device)\n",
        "            self.local.eval()\n",
        "            with torch.no_grad():\n",
        "                action_values = self.local(state)\n",
        "            self.local.train()\n",
        "            return np.argmax(action_values.cpu().data.numpy())\n",
        "        else:\n",
        "            return random.choice(np.arange(self.action_size))\n",
        "    def learn(self, experiences, gamma): \n",
        "        states, actions, rewards, next_states, dones = experiences\n",
        "       # Get expected Q values from local model\n",
        "        Q_expected = self.local(states).gather(1, actions)\n",
        "\n",
        "        # Get max predicted Q values (for next states) from local model\n",
        "        Q_targets_next = self.local(next_states).detach().max(1)[0].unsqueeze(1)\n",
        "        # Compute Q targets for current states \n",
        "        Q_targets = rewards + (gamma * Q_targets_next * (1 - dones))\n",
        "        \n",
        "        # Compute loss\n",
        "        loss = F.mse_loss(Q_expected, Q_targets)\n",
        "\n",
        "        # Minimize the loss\n",
        "        self.optimizer.zero_grad()\n",
        "        loss.backward()\n",
        "        self.optimizer.step()\n",
        "    def sample_experiences(self):\n",
        "        experiences = random.sample(self.memory, k=self.batch_size)        \n",
        "        states = torch.from_numpy(np.vstack([e.state for e in experiences if e is not None])).float().to(device)\n",
        "        actions = torch.from_numpy(np.vstack([e.action for e in experiences if e is not None])).long().to(device)\n",
        "        rewards = torch.from_numpy(np.vstack([e.reward for e in experiences if e is not None])).float().to(device)\n",
        "        next_states = torch.from_numpy(np.vstack([e.next_state for e in experiences if e is not None])).float().to(device)\n",
        "        dones = torch.from_numpy(np.vstack([e.done for e in experiences if e is not None]).astype(np.uint8)).float().to(device)        \n",
        "        return (states, actions, rewards, next_states, dones)\n",
        "agent = Agent(env.observation_space.shape[0], env.action_space.n)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Ov7oTYsYnowd"
      },
      "source": [
        "scores = [] # list containing scores from each episode\n",
        "scores_window = deque(maxlen=100) # last 100 scores\n",
        "n_episodes=5000\n",
        "max_t=5000\n",
        "eps_start=1.0\n",
        "eps_end=0.001\n",
        "eps_decay=0.9995\n",
        "eps = eps_start"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "mHOK_FWapNn7",
        "outputId": "9a7484a8-2a53-4647-ec5d-d4249ade4ed1",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 893
        }
      },
      "source": [
        "for i_episode in range(1, n_episodes+1):\n",
        "    state = env.reset()\n",
        "    state_size = env.observation_space.shape[0]\n",
        "    state = np.reshape(state, [1, state_size])\n",
        "    score = 0\n",
        "    for i in range(max_t):\n",
        "        action = agent.act(state, eps)\n",
        "        next_state, reward, done, _ = env.step(action)\n",
        "        next_state = np.reshape(next_state, [1, state_size])\n",
        "        reward = reward if not done or score == 499 else -10\n",
        "        agent.step(state, action, reward, next_state, done)\n",
        "        state = next_state\n",
        "        score += reward\n",
        "        if done:\n",
        "            break \n",
        "    scores_window.append(score) # save most recent score \n",
        "    scores.append(score) # save most recent score\n",
        "    eps = max(eps_end, eps_decay*eps) # decrease epsilon\n",
        "    print('\\rEpisode {}\\tReward {} \\tAverage Score: {:.2f} \\tEpsilon: {}'.format(i_episode,score,np.mean(scores_window), eps), end=\"\")\n",
        "    if i_episode % 100 == 0:\n",
        "        print('\\rEpisode {}\\tAverage Score: {:.2f} \\tEpsilon: {}'.format(i_episode, np.mean(scores_window), eps))\n",
        "    if i_episode>10 and np.mean(scores[-10:])>450:\n",
        "        break\n",
        "import matplotlib.pyplot as plt\n",
        "%matplotlib inline\n",
        "plt.plot(scores)\n",
        "plt.title('Scores over increasing episodes')"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Episode 100\tAverage Score: 11.83 \tEpsilon: 0.951217530242334\n",
            "Episode 200\tAverage Score: 16.20 \tEpsilon: 0.9048147898403269\n",
            "Episode 300\tAverage Score: 15.99 \tEpsilon: 0.8606756897186528\n",
            "Episode 400\tAverage Score: 23.94 \tEpsilon: 0.8186898039137951\n",
            "Episode 500\tAverage Score: 26.66 \tEpsilon: 0.7787520933134615\n",
            "Episode 600\tAverage Score: 31.67 \tEpsilon: 0.7407626428726788\n",
            "Episode 700\tAverage Score: 27.90 \tEpsilon: 0.7046264116491338\n",
            "Episode 800\tAverage Score: 39.22 \tEpsilon: 0.6702529950324074\n",
            "Episode 900\tAverage Score: 31.03 \tEpsilon: 0.637556398572254\n",
            "Episode 1000\tAverage Score: 47.30 \tEpsilon: 0.606454822840097\n",
            "Episode 1100\tAverage Score: 30.47 \tEpsilon: 0.5768704587855094\n",
            "Episode 1200\tAverage Score: 26.48 \tEpsilon: 0.548729293075715\n",
            "Episode 1300\tAverage Score: 25.61 \tEpsilon: 0.5219609229311034\n",
            "Episode 1400\tAverage Score: 20.64 \tEpsilon: 0.49649837999353363\n",
            "Episode 1500\tAverage Score: 25.36 \tEpsilon: 0.4722779627867691\n",
            "Episode 1600\tAverage Score: 34.30 \tEpsilon: 0.44923907734991153\n",
            "Episode 1700\tAverage Score: 28.26 \tEpsilon: 0.4273240856451275\n",
            "Episode 1800\tAverage Score: 43.74 \tEpsilon: 0.406478161360422\n",
            "Episode 1900\tAverage Score: 42.58 \tEpsilon: 0.3866491527467055\n",
            "Episode 2000\tAverage Score: 36.56 \tEpsilon: 0.3677874521460121\n",
            "Episode 2100\tAverage Score: 52.12 \tEpsilon: 0.34984587188445015\n",
            "Episode 2200\tAverage Score: 56.85 \tEpsilon: 0.3327795262194029\n",
            "Episode 2300\tAverage Score: 65.41 \tEpsilon: 0.31654571904563433\n",
            "Episode 2400\tAverage Score: 186.93 \tEpsilon: 0.3011038370793723\n",
            "Episode 2500\tAverage Score: 212.44 \tEpsilon: 0.28641524825313086\n",
            "Episode 2600\tAverage Score: 246.87 \tEpsilon: 0.27244320506708813\n",
            "Episode 2700\tAverage Score: 94.46 \tEpsilon: 0.25915275265522114\n",
            "Episode 2800\tAverage Score: 143.46 \tEpsilon: 0.24651064133620196\n",
            "Episode 2900\tAverage Score: 102.21 \tEpsilon: 0.23448524343027585\n",
            "Episode 3000\tAverage Score: 56.00 \tEpsilon: 0.22304647413401948\n",
            "Episode 3100\tAverage Score: 43.23 \tEpsilon: 0.21216571625502262\n",
            "Episode 3200\tAverage Score: 56.39 \tEpsilon: 0.2018157486181985\n",
            "Episode 3300\tAverage Score: 103.49 \tEpsilon: 0.1919706779646106\n",
            "Episode 3400\tAverage Score: 118.43 \tEpsilon: 0.1826058741724434\n",
            "Episode 3500\tAverage Score: 144.03 \tEpsilon: 0.17369790863805412\n",
            "Episode 3509\tReward 500.0 \tAverage Score: 173.83 \tEpsilon: 0.17291782950789983"
          ],
          "name": "stdout"
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "Text(0.5, 1.0, 'Scores over increasing episodes')"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 8
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": [],
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "CCoDl_OVpWhl"
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    }
  ]
}